import os
import sys
import shutil
from ruamel.yaml import YAML
from pathlib import Path
from typing import Dict, Any
from packaging import version

class ConfigManager:
    def __init__(self):
        self.yaml = YAML()
        self._init_paths()
        self.default_config = self._load_default_config()
        self.user_config = self._load_or_init_user_config()
        self.merged_config = self._merge_configs()

    def _init_paths(self):
        """初始化路径配置"""
        self.app_data_dir = Path(os.path.expandvars("%USERPROFILE%")) / "OfficeAIAssistant" / "data"
        self.user_config_path = self.app_data_dir / "settings" / "settings.yaml"

        # 判断是否是 PyInstaller 打包后的运行环境
        if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
            base_path = Path(sys._MEIPASS)
        else:
            base_path = Path(__file__).parent.parent
        self.default_config_path = base_path / "settings" / "settings.yaml"
            
        # 创建必要目录
        self.app_data_dir.mkdir(parents=True, exist_ok=True)

    def _load_default_config(self) -> Dict[str, Any]:
        """加载内置默认配置"""
        try:
            with open(self.default_config_path, 'r', encoding='utf-8') as f:
                return self.yaml.load(f) or {}
        except Exception as e:
            raise RuntimeError(f"加载默认配置失败: {str(e)}")

    def _load_or_init_user_config(self) -> Dict[str, Any]:
        """加载或初始化用户配置"""
        if not self.user_config_path.exists():
            self._create_initial_user_config()
        
        try:
            with open(self.user_config_path, 'r', encoding='utf-8') as f:
                return self.yaml.load(f) or {}
        except Exception as e:
            raise RuntimeError(f"加载用户配置失败: {str(e)}")

    def _create_initial_user_config(self):
        """创建初始用户配置文件"""
        user_settings_dir = self.user_config_path.parent
        user_settings_dir.mkdir(parents=True, exist_ok=True)
        shutil.copyfile(self.default_config_path, self.user_config_path)    

    def _merge_configs(self) -> Dict[str, Any]:
        """
        递归合并默认配置和用户配置
        用户配置优先，但保留 default 中 user 未覆盖的字段
        """
        
        def merge_dict(default: dict, user: dict) -> dict:
            """递归合并两个字典"""
            merged = default.copy()

            for key, value in user.items():
                # 如果键存在于两个字典中且都是字典，则递归合并
                if key in merged and isinstance(merged[key], dict) and isinstance(value, dict):
                    merged[key] = merge_dict(merged[key], value)
                # 如果是列表，直接替换（完全覆盖）
                elif isinstance(value, list):
                    merged[key] = value.copy()
                # 如果是集合，取并集
                elif isinstance(value, set):
                    merged[key] = merged.get(key, set()).union(value)
                # 其他类型直接更新（覆盖）
                else:
                    merged[key] = value

            return merged

        # 执行递归合并
        merged = merge_dict(self.default_config, self.user_config)
        return merged

    def check_config_version(self):
        """版本更新检测"""
        default_ver = self.default_config.get('metadata', {}).get('version', 0)
        user_ver = self.user_config.get('metadata', {}).get('version', 0)
        
        if version.Version(default_ver) > version.Version(user_ver):
            self._update_config_with_version()

    def _update_config_with_version(self):
        """执行版本更新合并"""
        merged = self._merge_configs()
        merged['metadata']['version'] = self.default_config['metadata']['version']
        self.save_user_config(merged)

    def save_user_config(self, config: Dict):
        """保存用户配置"""
        try:
            with open(self.user_config_path, 'w', encoding='utf-8') as f:
                self.yaml.dump(config, f)
        except Exception as e:
            raise RuntimeError(f"保存配置失败: {str(e)}")

        # 重新加载所有配置
        self.reload_configs()

    def reload_configs(self):
        """重新加载默认配置、用户配置和合并配置"""
        self.default_config = self._load_default_config()
        self.user_config = self._load_or_init_user_config()
        self.merged_config = self._merge_configs()

    def restore_default_config(self):
        """恢复默认配置"""
        self.save_user_config(self.default_config)

    def get_merged_config(self) -> Dict[str, Any]:
        """获取合并后的最终配置"""
        return self.merged_config